﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data;
using System.ComponentModel;
using System.Data.Common;

namespace WorkStation.Frameworks.Core.Data.Extensions
{
    /// <summary>
    /// * DataReader扩展类
    /// </summary>
    public static class DataReaderExtensions
    {
        /// <summary>
        /// * 判断DataReader是否有某一列
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="columnName">列名</param>
        /// <returns></returns>
        public static bool HasColumn(this IDataReader reader, string columnName) 
        {
            if (reader.GetSchemaTable().Select(string.Format("ColumnName='{0}'", columnName)).Count() == 0)
            {
                return false;
            }
            else 
            {
                return true;
            }
        }

        /// <summary>
        /// * 转化为实体列表
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <param name="reader">IDataReader</param>
        /// <returns></returns>
        public static List<TEntity> ToList2<TEntity>(this IDataReader reader) 
        {
            List<TEntity> res = new List<TEntity>();

            while (reader.Read()) 
            {
                TEntity entity = Activator.CreateInstance<TEntity>();

                foreach (PropertyInfo propertyInfo in entity.GetType().GetProperties()) 
                {
                    if (reader.HasColumn(propertyInfo.Name)) 
                    {
                        propertyInfo.SetValue(entity, AdaptType(reader[propertyInfo.Name], propertyInfo.PropertyType), null);
                    }
                }
            }

            return res;
        }

        /// <summary>
        /// * 适配类型
        /// </summary>
        /// <param name="value">需要适配的值</param>
        /// <param name="propertyType">适配的类型</param>
        /// <returns></returns>
        public static object AdaptType(object value, Type propertyType) 
        {
            // * 对可空类型特殊处理
            if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) 
            {
                if (value == null) { return null; }

                NullableConverter convert = new NullableConverter(propertyType);
                propertyType = convert.UnderlyingType;
            }

            // * 枚举类型特殊处理
            if (propertyType.IsEnum)
            {
                return Enum.ToObject(propertyType, value);
            }
            else 
            {
                return Convert.ChangeType(value, propertyType);
            }
        }


    }
}
